/***************************************************************
 * lora.autocomplete.js
 *
 * 插件名称: 文本框自动补全插件
 * jQuery版本:1.9+
 * 国际惯例：Bladnir 中国大陆 第二大区三战场组 奥拉基尔
 * 邮箱：bladnir@outlook.com
 * 创建时间：2016年9月7日
 * 描述：自动补全，可以使用键盘的 上下按钮操作 
 * 修改历史：
 * 
 * 参数说明： {
 *    属性名             默认值      说明
 *    width:            'auto'      auto 为自动适应文本框的宽度 如果为实际的数值 则固定按照这个数值的宽度来显示
 *    url :             null        必须传入的参数】，异步请求数据的url
 *    paramName :       'keyword'   查询的时候拼装的关键字参数名
 *    extendName:       'extend'    查询后的结果集的 扩展属性的名称
 *    textName:         'text'      查询后的结果集的 显示属性的名称
 *    contentFormatter: null        提示框中的文字格式化函数
 *    textFormatter:    null        选中后 文本框中的显示文字的格式化函数
 *    postSelect:       null        选中后的回调函数
 *    maxHeight:        220         提示框的默认最大高度（如果设置为0 则认为没有最大高度限制，高度完全取决于内容）
 *  }
 *  
 *  调用样例：
 *  
 * 		$("#inputText").autocomplete({
 *          url : 'xxxxx.do',
 *			contentFormatter : function( text, extend ){
 *				return text + ' '+ extend.email; 
 *			},
 * 			textFormatter : function(extend){
 *				return text;
 *			}, 
 *			postSelect : function(extend){
 *				
 *			}
 *		});	
 * 
 * 
 *********************************************************************/
(function ($) {

  /*
   * 自动补全 定义对象
   */
    var autoComplete = function(settings,targetInputObj){
    	
    	this.settings = settings;
    	this.targetInputObj = targetInputObj;
    	
    	//初始化
    	this.init = function(){
    		//获取自动补全提示框 对象
    		var autoTip = this.getAutoCompleteTip();
    		
            //在document注册mousedown，点击非div区域隐藏div
			$(document).bind('mousedown',function(event){
				var $target = $(event.target);
				if((!($target.parents().andSelf().is(autoTip))) && (!$target.is(targetInputObj))){
					$(autoTip).hide();
				}
			});
			
			this.blindKeyDown();
			this.blindKeyUp();
			this.blindFocus();
    	};
    	
    	//获取自动补全提示框 对象
    	this.getAutoCompleteTip = function(){
    		var tip = $('#autoCompleteLayout')[0];
    		if(!tip){
    			tip = $("<div/>").addClass('autocomplete-layout').attr('id','autoCompleteLayout');
    			$('body').append(tip);
    			return tip
    		}
    		return tip;
    	};
    	
    	//显示 自动补全提示框
    	this.showTip = function(){
    		var autoTip = this.getAutoCompleteTip();
    		var targetInputObj = this.targetInputObj;
    		var _this = this;
    		var inputOffset = $(targetInputObj).offset();
            $(autoTip).css("top", inputOffset.top + $(targetInputObj).height() + 5 + "px");
            $(autoTip).css("left", inputOffset.left + "px");
            
            if(this.settings.maxHeight !== 0){
            	$(autoTip).css("max-height", this.settings.maxHeight);
            }
            
            var tipWidth;
            if(this.settings.width === 'auto'){
            	tipWidth = $(this.targetInputObj).outerWidth(false);
            }else{
            	tipWidth = this.settings.width;
            }
            
            $(autoTip).width(tipWidth  + "px");
            
            if(!this.settings.data){//异步取数据
            	
            	var url = _this.settings.url;
            	var param = {};
            	param[_this.settings.paramName] = $(_this.targetInputObj).val();
            	
        		$.ajax({
        	        type: "POST",
        	        url: url,
        	        async:false,
        	        data: param, 
        	        success: function (data, textStatus, jqXHR) {
        	        	if(data && data.length > 0){
                            var ulObj = _this.creatContend(data);
                            $(autoTip).empty();
                            $(autoTip).append(ulObj);
        	        	}else{
        	    			//选中后的回调函数
        	    			var postSelect = _this.settings.postSelect;
        	    			if(postSelect !== null && typeof postSelect === 'function' ){
        	    				postSelect(null);
        	    			}
        	        		_this.hideTip();
        	        	}
        	        },
        	        error: function (XMLHttpRequest, textStatus, errorThrown) {
        	           $.error('autocomplete ajax request error');
        	        }
        	    });
            	
            }else{
            	//大部分情况 data有值的情况 是用于测试
                var ulObj = this.creatContend(this.settings.data);
                $(autoTip).empty();
                $(autoTip).append(ulObj);
            }
            
            $(autoTip).show();
    	};
    	
    	//创建提示框里面的内容
    	this.creatContend = function(data){
    		
    		var ulObj = $('<ul></ul>');
    		var targetInputObj = this.targetInputObj;
    		var _this = this;
    		if(data && data.length > 0){
    			$(data).each(function(index, entry){
    				
    				var liObj = $('<li></li>').data('celldata',entry).attr('acId',_this.getRandomNumber(6)).attr('isSelect','0');
    				var formatter = _this.settings.contentFormatter;
    				if(formatter != null && typeof formatter === 'function' ){
    					$(liObj).append(formatter(entry[_this.settings.textName] , entry));
    				}else{
    					$(liObj).append(entry[_this.settings.textName]);
    				}
    				
    				if(index%2 ==0){
    					$(liObj).addClass('autocomplete-li-odd');
    				}
    				
    				$(liObj).click(function(){//点击
    					_this.selectLi($(this).attr('acId'));
    				}).mousemove(function(){//滑过
    					liArray = $(ulObj).find('li');
    					var _thisLi = $(this);
    					$(liArray).each(function(index,entry){
    						if($(entry).is(_thisLi)){
    							$(entry).addClass('autocomplete-li-select');
    							$(entry).attr('isSelect','1');
    						}else{
    							$(entry).removeClass('autocomplete-li-select');
    							$(entry).attr('isSelect','0');
    						}
    					});
    				});
    				
    				$(ulObj).append(liObj);
    			});
    		}
    		
    		return ulObj;
    		
    	};
    	
    	//选中一个li
    	this.selectLi = function(acId){
    		var autoTip = this.getAutoCompleteTip();
    		var targetInputObj = this.targetInputObj;
    		
    		var selectLiObj = $(autoTip).find('li[acId="'+acId+'"]');
    		
    		var celldata = $(selectLiObj).data('celldata'); 
    		
    		var textFormatter = this.settings.textFormatter;
			
			var text = '';
			if(textFormatter !== null && typeof textFormatter === 'function' ){
				text = textFormatter(celldata);
			}else{
				text = $(selectLiObj).html();
			}
			targetInputObj.val(text);
			//隐藏提示框
			this.hideTip();
			
			//选中后的回调函数
			var postSelect = this.settings.postSelect;
			if(postSelect !== null && typeof postSelect === 'function' ){
				postSelect(celldata);
			}
    		
    	};
    	
    	//隐藏 自动补全提示框
    	this.hideTip = function(){
    		var autoTip = this.getAutoCompleteTip();
    		$(autoTip).hide();
    	};
    	
    	//生成id
    	this.getRandomNumber = function(lenght){
    		if(!lenght){
    			lenght = 6;
    		}
    		var str = '';
    		var date = new Date();
    		var dateStr = date.getTime()+'';
    		for(var i=0;i<lenght;i++){
    			str = str + Math.floor(Math.random()*10);
    		}
    		str = dateStr + str;
    		return str;
    	};
    	
    	//绑定keyup事件
    	this.blindKeyUp = function(){
    		var _this = this;
    		$(this.targetInputObj).keyup(function (event) {
    			
    			//按下的键是否是功能键
    			var isFunctionalKey = $.inArray(event.keyCode, _this.settings.functionalKeyArray);  
    			var ctrl = event.ctrlKey;
    			var k = event.keyCode;
    			
    			//k键值不是功能键或是ctrl+c、ctrl+x时才触发自动补全功能
    			if(isFunctionalKey == -1 && (!ctrl || (ctrl && k == 67) || (ctrl && k == 88)) ){
    				//重新计算提示框里面的内容
    				_this.showTip();
    			}
    			
    		});
    	};
    	
    	//绑定change事件
    	this.blindFocus  = function(){
    		var _this =  this;
    		var targetInputObj = this.targetInputObj
    		 $(targetInputObj).focus(function(){
    			 if($(targetInputObj).val() == ''){
     				//重新计算提示框里面的内容
     				_this.showTip();
    			 }
    		 });
    	};
    	
    	//绑定 文本框keydown事件
    	this.blindKeyDown = function(){
    		var keys = this.settings.keys;
            var _this = this;

            $(this.targetInputObj).keydown(function (event) {

            	if(event.keyCode == keys.UP){//向上键
            		
                    var autoTip = _this.getAutoCompleteTip();
                    var ulObj = $(autoTip).find('ul');
                    var liArray = $(ulObj).find('li');
            		var selectLiObj = $(autoTip).find('li[isSelect="1"]')[0];
            		
            		var liObj;
            		if(selectLiObj){//有选中的li
            			var index = $(selectLiObj).index();
            			if(index == 0){//如果选中的li是第一个 选中最后面的li
                			var last = $(liArray).length - 1;
                			liObj = $(liArray).get(last);
            			}else{//不是第一个 则选择上一个li
            				liObj = $(liArray).get(index-1);
            			}
            			
            		}else{//没有选中的li 选中最后面的li
            			var last = $(liArray).length - 1;
            			var liObj = $(liArray).get(last);
            		}
            		$(selectLiObj).attr('isSelect','0');
            		$(selectLiObj).removeClass('autocomplete-li-select');
					$(liObj).addClass('autocomplete-li-select');
					$(liObj).attr('isSelect','1');
					
					//滚动 到目前选中的li的位置
					$('#eventCode').val($(liObj).offset().top);
					if($(liObj).index() == 0){
						$(autoTip).animate({scrollTop: 0}, 100,'linear');
					}else{
						$(autoTip).animate({scrollTop: $(liObj).offset().top}, 100,'linear');
					}
					
            	}else if(event.keyCode == keys.DOWN){//向下键
            		
                    var autoTip = _this.getAutoCompleteTip();
                    var ulObj = $(autoTip).find('ul');
                    var liArray = $(ulObj).find('li');
            		var selectLiObj = $(autoTip).find('li[isSelect="1"]')[0];
            		var liObj;
            		if(selectLiObj){//有选中的li
            			var index = $(selectLiObj).index();
            			var last = $(liArray).length - 1;
            			
            			if(index == last){//如果选中的li是最后一个 则选中第一个
                			liObj = $(liArray).get(0);
            			}else{//不是最后一个 则选择下一个li
            				liObj = $(liArray).get(index+1);
            			}
            		}else{//没有选中的li 选中第一个li
            			liObj = $(liArray).get(0);
            		}
            		$(selectLiObj).attr('isSelect','0');
            		$(selectLiObj).removeClass('autocomplete-li-select');
					$(liObj).addClass('autocomplete-li-select');
					$(liObj).attr('isSelect','1');
					
					//滚动 到目前选中的li的位置
					if($(liObj).index() === 0){
						$(autoTip).animate({scrollTop: 0}, 100,'linear');
					}else{
						$(autoTip).animate({scrollTop: $(liObj).offset().top}, 100,'linear');
					}
            		
            	}else if(event.keyCode === keys.ESC){//ESC键
            		_this.hideTip();
            	}else if(event.keyCode === keys.ENTER){//ENTER键
            	   //选中当前的焦点的li
            		var autoTip = _this.getAutoCompleteTip();
            		var selectLiObj = $(autoTip).find('li[isSelect="1"]')[0];
            		if(selectLiObj){
            			var acId = $(selectLiObj).attr('acId');
            			_this.selectLi(acId);
            		}
            		
            		_this.hideTip();
            	}
            	
            });
    	};
    	
    };
    

	
	/**
	 *  Main Entrance
	 */
	$.fn.autocomplete = function(arg0) {

		if(typeof arg0 === 'object'){
			var opts = $.extend({}, $.fn.autocomplete.defaults, arg0);
			var acObj = new autoComplete(opts,$(this));
			acObj.init();
		}else{
			$.error('Autocomplete Main Entrance Error');
		}

	}
	
	/**
	 * Default Configuration
	 */
	$.fn.autocomplete.defaults = {
	        width: 'auto',
	        paramName: 'keyword',
	        extendName : 'extend',
	        textName : 'text',
	        data : null,
	        url : '',
	        contentFormatter : null,
	        textFormatter : null,
	        maxHeight : 220,
	        keys : {
                UP: 38,
                DOWN: 40,
                DEL: 46,
                TAB: 9,
                ENTER: 13,
                ESC: 27,
                /*COMMA: 188,*/
                PAGEUP: 33,
                PAGEDOWN: 34,
                BACKSPACE: 8,
                A: 65,
                Z: 90
            },
            functionalKeyArray : [9,20,13,16,17,18,91,92,93,45,36,33,34,35,37,39,112,113,114,115,116,117,118,119,120,121,122,123,144,19,145,40,38,27]
	}
  
})(jQuery);